"""
权限数据访问层
封装权限模型的数据库操作
"""
from typing import List, Optional, Dict, Any, Tuple
from tortoise.expressions import Q
from tortoise.functions import Count

from apps.auth.models.permission import Permission
from apps.auth.models.role import Role
from apps.auth.models.user import User
from apps.auth.models.relations import UserPermission, RolePermission


class PermissionRepository:
    """权限数据访问层"""
    
    @staticmethod
    async def create(permission_data: Dict[str, Any]) -> Permission:
        """
        创建权限
        :param permission_data: 权限数据字典
        :return: 创建的权限实例
        """
        permission = await Permission.create(**permission_data)
        return permission
    
    @staticmethod
    async def get_by_id(permission_id: int) -> Optional[Permission]:
        """
        通过ID获取权限
        :param permission_id: 权限ID
        :return: 权限实例或None
        """
        return await Permission.filter(id=permission_id, is_deleted=False).first()
    
    @staticmethod
    async def get_by_slug(slug: str) -> Optional[Permission]:
        """
        通过标识获取权限
        :param slug: 权限标识
        :return: 权限实例或None
        """
        return await Permission.filter(slug=slug, is_deleted=False).first()
    
    @staticmethod
    async def list_permissions(
        page: int = 1, 
        page_size: int = 10,
        search: Optional[str] = None,
        module: Optional[str] = None,
        order_by: str = "module"
    ) -> Tuple[List[Permission], int]:
        """
        获取权限列表
        :param page: 页码
        :param page_size: 每页大小
        :param search: 搜索关键词(名称/标识/描述)
        :param module: 按模块过滤
        :param order_by: 排序字段
        :return: 权限列表和总数
        """
        # 构建基本查询
        query = Permission.filter(is_deleted=False)
        
        # 应用过滤条件
        if search:
            query = query.filter(
                Q(name__icontains=search) | 
                Q(slug__icontains=search) | 
                Q(description__icontains=search)
            )
        
        if module:
            query = query.filter(module=module)
        
        # 计算总数
        total = await query.count()
        
        # 获取分页数据
        if order_by == "module":
            # 如果按模块排序，则二级排序按动作
            permissions = await query.order_by("module", "action").offset((page - 1) * page_size).limit(page_size).all()
        else:
            permissions = await query.order_by(order_by).offset((page - 1) * page_size).limit(page_size).all()
        
        return permissions, total
    
    @staticmethod
    async def get_modules() -> List[str]:
        """
        获取所有权限模块名称列表
        :return: 模块名称列表
        """
        modules = await Permission.filter(is_deleted=False).distinct().values_list('module', flat=True)
        return sorted(modules)
    
    @staticmethod
    async def update(permission: Permission, update_data: Dict[str, Any]) -> Permission:
        """
        更新权限信息
        :param permission: 权限实例
        :param update_data: 更新的字段数据
        :return: 更新后的权限实例
        """
        # 过滤掉None值，只更新提供了的字段
        valid_updates = {k: v for k, v in update_data.items() if v is not None}
        
        # 更新权限实例字段
        for key, value in valid_updates.items():
            setattr(permission, key, value)
            
        # 保存到数据库
        await permission.save()
        
        return permission
    
    @staticmethod
    async def update_whole(permission: Permission, update_data: Dict[str, Any]) -> Permission:
        """
        全部更新权限信息
        :param permission: 权限实例
        :param update_data: 完整的更新数据
        :return: 更新后的权限实例
        """
        # 更新所有字段，包括未提供的字段(设为默认值)
        for key, value in update_data.items():
            setattr(permission, key, value)
            
        await permission.save()
        
        return permission
    
    @staticmethod
    async def delete(permission: Permission) -> None:
        """
        软删除权限
        :param permission: 权限实例
        """
        await permission.soft_delete()
    
    @staticmethod
    async def hard_delete(permission: Permission) -> None:
        """
        硬删除权限(永久删除)
        :param permission: 权限实例
        """
        await permission.delete()
    
    @staticmethod
    async def exists_by_id(permission_id: int) -> bool:
        """
        检查权限ID是否存在
        :param permission_id: 权限ID
        :return: 是否存在
        """
        return await Permission.filter(id=permission_id, is_deleted=False).exists()
    
    @staticmethod
    async def exists_by_slug(slug: str) -> bool:
        """
        检查权限标识是否存在
        :param slug: 权限标识
        :return: 是否存在
        """
        return await Permission.filter(slug=slug, is_deleted=False).exists()
    
    @staticmethod
    async def get_permission_roles(permission_id: int) -> List[Role]:
        """
        获取拥有指定权限的所有角色
        :param permission_id: 权限ID
        :return: 角色列表
        """
        roles = await Role.filter(
            role_permissions__permission_id=permission_id,
            is_deleted=False
        ).all()
        
        return roles
    
    @staticmethod
    async def get_permission_users(permission_id: int) -> List[User]:
        """
        获取拥有指定权限的所有用户(直接权限)
        :param permission_id: 权限ID
        :return: 用户列表
        """
        users = await User.filter(
            user_permissions__permission_id=permission_id,
            is_deleted=False
        ).all()
        
        return users
    
    @staticmethod
    async def assign_to_user(permission_id: int, user_id: int) -> bool:
        """
        将权限直接分配给用户
        :param permission_id: 权限ID
        :param user_id: 用户ID
        :return: 是否成功
        """
        # 检查关联是否已存在
        exists = await UserPermission.filter(
            user_id=user_id,
            permission_id=permission_id
        ).exists()
        
        if not exists:
            await UserPermission.create(
                user_id=user_id,
                permission_id=permission_id
            )
            return True
            
        return False
    
    @staticmethod
    async def remove_from_user(permission_id: int, user_id: int) -> bool:
        """
        移除用户的直接权限
        :param permission_id: 权限ID
        :param user_id: 用户ID
        :return: 是否成功
        """
        deleted_count = await UserPermission.filter(
            user_id=user_id,
            permission_id=permission_id
        ).delete()
        
        return deleted_count > 0
